package com.sapuo.enroll.utils;

import org.springframework.stereotype.Component;

import java.util.Random;

/**
 * Created by tao.
 * Date: 2021/6/28 16:43
 * 描述:
 */
@Component
public class CDKeyUtil {

    //机器版本号

    /**
     * 激活码生成方法
     *
     * @param category 密钥类别（固定两位数字）
     * @param deadline 使用期限（固定一位字符）
     * @return 返回的激活码
     */
    public static String createCDkey(String category, String deadline, String machineVersion) throws Exception {
        String CDKey = "";
        //1. 获取前四位
        String sequence = getSequence();
        //2. 生成前七位
        String plaintext = sequence + category + deadline;
        //3.对明文进行加密
        CDKey = CDKeyEncryptUtils.AESencrypt(plaintext).substring(0, 11);
        //4.获取后四位
        String rulesSequence = CDKeyUtil.getRulesSequence(machineVersion);
        //5.混淆操作
        CDKey = CDKey + rulesSequence;
        CDKey = confusion(CDKey);
        //6.得到激活码
        return CDKey;
    }

    /**
     * 激活码解码方法
     *
     * @param CDKey 激活码
     * @return 返回激活码明文
     */
    public static String deCDkey(String CDKey, String machineVersion) throws Exception {
        //1. 解除混淆
        String deConfusion = deConfusion(CDKey);
        //2. 提取后四位序列(第1位版本号，后三位校验其规则)
        String sequence = deConfusion.substring(deConfusion.length() - 4);
        //3. 获取后三位序列并且转为10进制，和版本号
        String randomInt = sequence.substring(1);
        String version = sequence.substring(0, 1);
        int to10 = Integer.parseInt(change32To10(randomInt));
        //4. 根据既定规则校验激活码是否正确
        if (to10 % 11 == 0 && version.equals(machineVersion)) {
            //1. 如果后四位序列校验正确,则对激活码进行解密操作
            String secretKey = deConfusion.substring(0, 11);
            String code = "";
            try {
                code = CDKeyEncryptUtils.AESdecrypt(secretKey);
            } catch (Exception e) {
                e.printStackTrace();
                return "0";
            }
            return code;
        } else {
            return "0";
        }

    }

    /**
     * 获得激活码前四位序列方法
     *
     * @return 返回激活码前四位序列
     */
    public static String getSequence() {
        String sequence = "";
        //1. 获取随机数
        int randomInt = getRandomInt();
        //2. 转32进制
        String to32 = change10To32(randomInt + "");
        //3. 补全四位
        int len = to32.length();
        if (len < 4) {
            for (int i = 0; i < 4 - len; i++) {
                to32 = "0" + to32;
            }
        }
        sequence = to32;
        return sequence;
    }

    /**
     * 获得激活码后四位规则序列方法
     *
     * @param machineVersion 机器版本号
     * @return 返回激活码后四位规则序列
     */
    public static String getRulesSequence(String machineVersion) {
        String rulesSequence;
        //1. 按照规则获取前三位
        /*int randomInt = new Random().nextInt(8);
        String randomStr = randomInt + "" + (randomInt + 1) + (randomInt + 2);*/

        //1. 按照规则获取前三位
        int randomInt = new Random().nextInt(2500);
        String randomStr = (randomInt * 11) + "";
        //2. 转32进制
        String to32 = change10To32(randomStr);
        //3. 补全三位
        int len = to32.length();
        if (len < 3) {
            for (int i = 0; i < 3 - len; i++) {
                to32 = "0" + to32;
            }
        }
        //4.拼接第四位
        rulesSequence = machineVersion + to32;
        return rulesSequence;
    }

    /**
     * 激活码混淆方法
     * 奇数位+偶数位
     *
     * @return 返回激活码混淆后的序列
     */
    public static String confusion(String CDKey) {
        String deCDKey = "";
        //1.获取奇数位字串
        String odd = "";
        for (int i = 0; i < CDKey.length(); i = i + 2) {
            odd = odd + CDKey.charAt(i);
        }
        //2.获取偶数位字串
        String even = "";
        for (int i = 1; i < CDKey.length(); i = i + 2) {
            even = even + CDKey.charAt(i);
        }
        //3.拼接
        deCDKey = odd + even;
        return deCDKey;
    }

    /**
     * 激活码解除混淆方法
     *
     * @return 返回激活码解除混淆后的序列
     */
    public static String deConfusion(String deCDKey) {
        String CDKey = "";
        //1. 拆分
        int oddCount = (deCDKey.length() / 2) + (deCDKey.length() % 2);
        String odd = deCDKey.substring(0, oddCount);
        String even = deCDKey.substring(oddCount);
        //2. 复原激活码
        if (odd.length() == even.length()) {
            for (int i = 0; i < odd.length(); i++) {
                CDKey = CDKey + odd.charAt(i) + even.charAt(i);
            }
        } else {
            for (int i = 0; i < even.length(); i++) {
                CDKey = CDKey + odd.charAt(i) + even.charAt(i);
            }
            CDKey = CDKey + odd.charAt(odd.length() - 1);
        }
        return CDKey;
    }

    /**
     * 10进制转32进制的方法
     * num 要转换的数 from源数的进制 to要转换成的进制
     *
     * @param num 10进制(字符串)
     * @return 转换结果的32进制字符串
     */
    public static String change10To32(String num) {
        int from = 10;
        int to = 32;
        return new java.math.BigInteger(num, from).toString(to);
    }

    /**
     * 32进制转10进制的方法
     * num 要转换的数 from源数的进制 to要转换成的进制
     *
     * @param num 10进制(字符串)
     * @return 转换结果的10进制字符串
     */
    public static String change32To10(String num) {
        int f = 32;
        int t = 10;
        return new java.math.BigInteger(num, f).toString(t);
    }

    /**
     * 生成[min, max]之间的随机整数
     * min 最小整数(固定0)
     * max 最大整数(固定1000000)
     *
     * @return 返回min———max之间的随机数
     * @author tao
     */
    public static int getRandomInt() {
        int min = 0;
        int max = 1000000;
        return new Random().nextInt(max) % (max - min + 1) + min;
    }

    /*
     * 枚举日期，返回天数
     */
    public static int duetimeEnum(String code) {
        switch (code) {
            case "0":
                return 36500;
            case "1":
                return 7;
            case "2":
                return 30;
            case "3":
                return 90;
            case "4":
                return 180;
            case "5":
                return 365;
            default:
                return 30;
        }
    }
}